<Project Sdk="Microsoft.Build.NoTargets">

  <UsingTask TaskName="Microsoft.WebAssembly.Build.Tasks.RunWithEmSdkEnv" AssemblyFile="$(WasmAppBuilderTasksAssemblyPath)" />

  <PropertyGroup>
    <!-- FIXME: clean up the duplication with libraries Directory.Build.props -->
    <PackageRID>browser-wasm</PackageRID>
    <NativeBinDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'native', '$(NetCoreAppCurrent)-$(TargetOS)-$(Configuration)-$(TargetArchitecture)'))</NativeBinDir>
    <!-- only use for files that are not configuration dependent -->
    <NativeGeneratedFilesDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'native', 'generated'))</NativeGeneratedFilesDir>
  </PropertyGroup>

  <PropertyGroup>
    <PythonCmd Condition="'$(HostOS)' != 'windows'">python3</PythonCmd>
    <PythonCmd Condition="'$(HostOS)' == 'windows'">python</PythonCmd>
  </PropertyGroup>

  <PropertyGroup>
    <MonoDiagnosticsMock Condition="'$(MonoDiagnosticsMock)' == '' and '$(Configuration)' == 'Release'">false</MonoDiagnosticsMock>
    <MonoDiagnosticsMock Condition="'$(MonoDiagnosticsMock)' == '' and '$(Configuration)' == 'Debug'">true</MonoDiagnosticsMock>
  </PropertyGroup>

  <PropertyGroup>
    <ICULibDir Condition="'$(WasmEnableThreads)' != 'true'">$([MSBuild]::NormalizeDirectory('$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)', 'runtimes', 'browser-wasm', 'native', 'lib'))</ICULibDir>
    <ICULibDir Condition="'$(WasmEnableThreads)' == 'true'">$([MSBuild]::NormalizeDirectory('$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)', 'runtimes', 'browser-wasm-threads', 'native', 'lib'))</ICULibDir>
    <WasmEnableSIMD Condition="'$(WasmEnableSIMD)' == ''">true</WasmEnableSIMD>
    <WasmEnableExceptionHandling Condition="'$(WasmEnableExceptionHandling)' == ''">true</WasmEnableExceptionHandling>
    <WasmEnableJsInteropByValue Condition="'$(WasmEnableJsInteropByValue)' == '' and '$(WasmEnableThreads)' == 'true'">true</WasmEnableJsInteropByValue>
    <WasmEnableJsInteropByValue Condition="'$(WasmEnableJsInteropByValue)' == ''">false</WasmEnableJsInteropByValue>
    <FilterSystemTimeZones Condition="'$(FilterSystemTimeZones)' == ''">false</FilterSystemTimeZones>
    <EmccCmd>emcc</EmccCmd>
    <WasmObjDir>$(ArtifactsObjDir)wasm</WasmObjDir>
    <_EmccDefaultsRspPath>$(NativeBinDir)src\emcc-default.rsp</_EmccDefaultsRspPath>
    <_EmccCompileRspPath>$(NativeBinDir)src\emcc-compile.rsp</_EmccCompileRspPath>
    <_EmccLinkRspPath>$(NativeBinDir)src\emcc-link.rsp</_EmccLinkRspPath>
    <EmSdkLLVMAr>$(EMSDK_PATH)\upstream\bin\llvm-ar</EmSdkLLVMAr>
    <EmSdkLLVMAr Condition="$([MSBuild]::IsOSPlatform('Windows'))">$(EmSdkLLVMAr).exe</EmSdkLLVMAr>
  </PropertyGroup>

  <Target Name="CheckEnv">
    <Error Condition="'$(TargetArchitecture)' != 'wasm'" Text="Expected TargetArchitecture==wasm, got '$(TargetArchitecture)'"/>
    <Error Condition="'$(TargetOS)' != 'browser'" Text="Expected TargetOS==browser, got '$(TargetOS)'"/>
    <Error Condition="'$(EMSDK_PATH)' == ''" Text="The EMSDK_PATH environment variable should be set pointing to the emscripten SDK root dir."/>
  </Target>

  <ItemGroup>
    <PackageReference Include="Microsoft.NETCore.Runtime.ICU.Transport" PrivateAssets="all" Version="$(MicrosoftNETCoreRuntimeICUTransportVersion)" GeneratePathProperty="true" />
    <PackageReference Include="System.Runtime.TimeZoneData" PrivateAssets="all" Version="$(SystemRuntimeTimeZoneDataVersion)" GeneratePathProperty="true" />
  </ItemGroup>

  <UsingTask TaskName="ManagedToNativeGenerator" AssemblyFile="$(WasmAppBuilderTasksAssemblyPath)" />
  <Target Name="GenerateManagedToNative" DependsOnTargets="CheckEnv;ResolveLibrariesFromLocalBuild">
    <PropertyGroup>
      <WasmPInvokeTablePath>$(WasmObjDir)\pinvoke-table.h</WasmPInvokeTablePath>
      <WasmInterpToNativeTablePath>$(WasmObjDir)\wasm_m2n_invoke.g.h</WasmInterpToNativeTablePath>
    </PropertyGroup>

    <ItemGroup>
      <WasmPInvokeModule Include="libSystem.Native" />
      <WasmPInvokeModule Include="libSystem.IO.Compression.Native" />
      <WasmPInvokeModule Include="libSystem.Globalization.Native" />
      <WasmPInvokeAssembly Include="@(LibrariesRuntimeFiles)" Condition="'%(Extension)' == '.dll' and '%(IsNative)' != 'true'" />
    </ItemGroup>

    <!-- Retrieve CoreLib's targetpath via GetTargetPath as it isn't binplaced yet. -->
    <MSBuild Projects="$(CoreLibProject)"
             Targets="GetTargetPath">
      <Output TaskParameter="TargetOutputs" ItemName="WasmPInvokeAssembly" />
    </MSBuild>

    <MakeDir Directories="$(WasmObjDir)" Condition="!Exists('$(WasmObjDir)')" />

    <ManagedToNativeGenerator
      Assemblies="@(WasmPInvokeAssembly)"
      PInvokeModules="@(WasmPInvokeModule)"
      PInvokeOutputPath="$(WasmPInvokeTablePath)"
      InterpToNativeOutputPath="$(WasmInterpToNativeTablePath)">
      <Output TaskParameter="FileWrites" ItemName="FileWrites" />
    </ManagedToNativeGenerator>
  </Target>

  <UsingTask TaskName="EmitBundleSourceFiles" AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
  <Target Name="GenerateTimezonesArchive" Returns="@(_WasmArchivedTimezones)" Condition="'$(InvariantTimezone)' != 'true'">
    <PropertyGroup>
      <_WasmTimezonesPath>$([MSBuild]::NormalizePath('$(PkgSystem_Runtime_TimeZoneData)', 'contentFiles', 'any', 'any', 'data'))</_WasmTimezonesPath>
      <_WasmTimezonesBundleSourceFile>wasm-bundled-timezones.c</_WasmTimezonesBundleSourceFile>
      <_WasmTimezonesBundleArchive>$(WasmObjDir)\wasm-bundled-timezones.a</_WasmTimezonesBundleArchive>
      <_WasmTimezonesSourcesRsp>$(WasmObjDir)\wasm-bundled-timezones-sources.rsp</_WasmTimezonesSourcesRsp>
      <_WasmTimezonesArchiveRsp>$(WasmObjDir)\wasm-bundled-timezones-archive.rsp</_WasmTimezonesArchiveRsp>
    </PropertyGroup>
    <ItemGroup>
      <_WasmTimezonesInternal Include="$(_WasmTimezonesPath)\**\*.*" WasmRole="Timezone"/>
    </ItemGroup>
    <ItemGroup>
      <_WasmTimezonesInternal Update="@(_WasmTimezonesInternal)">
        <RegisteredName>/usr/share/zoneinfo/$([MSBuild]::MakeRelative($(_WasmTimezonesPath), %(_WasmTimezonesInternal.Identity)).Replace('\','/'))</RegisteredName>
      </_WasmTimezonesInternal>
    </ItemGroup>
    <!-- TODO make this incremental compilation -->
    <EmitBundleSourceFiles
      FilesToBundle="@(_WasmTimezonesInternal)"
      BundleRegistrationFunctionName="mono_register_timezones_bundle"
      BundleFile="$(_WasmTimezonesBundleSourceFile)"
      OutputDirectory="$(WasmObjDir)">
      <Output TaskParameter="BundledResources" ItemName="BundledWasmTimezones" />
    </EmitBundleSourceFiles>

    <ItemGroup>
      <_WasmBundleTimezonesSources Include="$([MSBuild]::MakeRelative($(WasmObjDir), %(BundledWasmTimezones.DestinationFile)).Replace('\','/'))" />
      <_WasmBundleTimezonesSources Include="$(_WasmTimezonesBundleSourceFile)" />
    </ItemGroup>
    <WriteLinesToFile File="$(_WasmTimezonesSourcesRsp)"
      Overwrite="true"
      Lines="@(_WasmBundleTimezonesSources, ' ')"
      WriteOnlyWhenDifferent="true" />
    <RunWithEmSdkEnv Command="$(EmccCmd) -xc -c @$(_WasmTimezonesSourcesRsp)"
          WorkingDirectory="$(WasmObjDir)"
          EmSdkPath="$(EMSDK_PATH)"
          ConsoleToMsBuild="true"
          IgnoreStandardErrorWarningFormat="true">
    </RunWithEmSdkEnv>
    <ItemGroup>
      <WasmBundleTimezonesObjects Include="%(_WasmBundleTimezonesSources.Filename).o" />
    </ItemGroup>
    <WriteLinesToFile File="$(_WasmTimezonesArchiveRsp)"
      Overwrite="true"
      Lines="@(WasmBundleTimezonesObjects, ' ')"
      WriteOnlyWhenDifferent="true" />
    <RunWithEmSdkEnv Command="$(EmSdkLLVMAr) cs -r $(_WasmTimezonesBundleArchive) @$(_WasmTimezonesArchiveRsp)"
          EmSdkPath="$(EMSDK_PATH)"
          WorkingDirectory="$(WasmObjDir)"
          ConsoleToMsBuild="true"
          IgnoreStandardErrorWarningFormat="true">
    </RunWithEmSdkEnv>

    <ItemGroup>
      <_WasmArchivedTimezones Include="$(WasmObjDir)\wasm-bundled-timezones.a" />
    </ItemGroup>

    <!-- Clean up the bundle-objects dir - remove anything we no longer need -->
    <ItemGroup>
      <_WasmBundleTimezonesToDelete Include="$(_WasmIntermediateOutputPath)*.o" />
      <_WasmBundleTimezonesToDelete Include="$(_WasmIntermediateOutputPath)*.c" />
      <_WasmBundleTimezonesToDelete Remove="$(WasmObjDir)\$(_WasmTimezonesBundleSourceFile)" />
      <_WasmBundleTimezonesToDelete Remove="%(BundledWasmTimezones.DestinationFile)" />
      <_WasmBundleTimezonesToDelete Remove="$(WasmObjDir)\%(WasmBundleTimezonesObjects)" />
    </ItemGroup>
    <Delete Files="@(_WasmBundleTimezonesToDelete)" />
  </Target>

  <Target Name="GenerateEmccPropsAndRspFiles">

    <!-- Generate wasm-props.json -->

    <RunWithEmSdkEnv Command="$(EmccCmd) --version"
          ConsoleToMsBuild="true"
          EmSdkPath="$(EMSDK_PATH)"
          IgnoreStandardErrorWarningFormat="true">
      <Output TaskParameter="ConsoleOutput" ItemName="_VersionLines" />
    </RunWithEmSdkEnv>

    <!-- we want to get the first line from the output, which has the version.
         Rest of the lines are the license -->
    <ItemGroup>
      <_ReversedVersionLines Include="@(_VersionLines->Reverse())" />
    </ItemGroup>
    <PropertyGroup>
      <_EmccVersionRaw>%(_ReversedVersionLines.Identity)</_EmccVersionRaw>

      <_EmccVersionRegexPattern>^ *emcc \([^\)]+\) *([0-9\.]+).*\(([^\)]+)\)$</_EmccVersionRegexPattern>
      <_EmccVersion>$([System.Text.RegularExpressions.Regex]::Match($(_EmccVersionRaw), $(_EmccVersionRegexPattern)).Groups[1].Value)</_EmccVersion>
      <_EmccVersionHash>$([System.Text.RegularExpressions.Regex]::Match($(_EmccVersionRaw), $(_EmccVersionRegexPattern)).Groups[2].Value)</_EmccVersionHash>
    </PropertyGroup>

    <Error Text="Failed to parse emcc version, and hash from the full version string: '$(_EmccVersionRaw)'"
           Condition="'$(_EmccVersion)' == '' or '$(_EmccVersionHash)' == ''" />

    <ItemGroup>
      <EmccExportedRuntimeMethod Include="FS" />
      <EmccExportedRuntimeMethod Include="out" />
      <EmccExportedRuntimeMethod Include="err" />
      <EmccExportedRuntimeMethod Include="ccall" />
      <EmccExportedRuntimeMethod Include="cwrap" />
      <EmccExportedRuntimeMethod Include="setValue" />
      <EmccExportedRuntimeMethod Include="getValue" />
      <EmccExportedRuntimeMethod Include="UTF8ToString" />
      <EmccExportedRuntimeMethod Include="UTF8ArrayToString" />
      <EmccExportedRuntimeMethod Include="stringToUTF8Array" />
      <EmccExportedRuntimeMethod Include="FS_createPath" />
      <EmccExportedRuntimeMethod Include="FS_createDataFile" />
      <EmccExportedRuntimeMethod Include="removeRunDependency" />
      <EmccExportedRuntimeMethod Include="addRunDependency" />
      <EmccExportedRuntimeMethod Include="addFunction" />
      <EmccExportedRuntimeMethod Include="safeSetTimeout" />
      <EmccExportedRuntimeMethod Include="runtimeKeepalivePush" />
      <EmccExportedRuntimeMethod Include="runtimeKeepalivePop" />
      <EmccExportedRuntimeMethod Include="maybeExit" />
      <EmccExportedRuntimeMethod Include="abort" />

      <EmccExportedFunction Include="_free" />
      <EmccExportedFunction Include="_htons" />
      <EmccExportedFunction Include="_malloc" />
      <EmccExportedFunction Include="_memalign" />
      <EmccExportedFunction Include="_memset" />
      <EmccExportedFunction Include="_ntohs" />
      <EmccExportedFunction Include="stackAlloc" />
      <EmccExportedFunction Include="stackRestore" />
      <EmccExportedFunction Include="stackSave"  />
    </ItemGroup>
    <!-- for the jiterpreter -->
    <ItemGroup>
      <EmccExportedFunction Include="_fmod" />
      <EmccExportedFunction Include="_atan2" />
      <EmccExportedFunction Include="_fma" />
      <EmccExportedFunction Include="_pow" />
      <EmccExportedFunction Include="_fmodf" />
      <EmccExportedFunction Include="_atan2f" />
      <EmccExportedFunction Include="_fmaf" />
      <EmccExportedFunction Include="_powf" />

      <EmccExportedFunction Include="_asin" />
      <EmccExportedFunction Include="_asinh" />
      <EmccExportedFunction Include="_acos" />
      <EmccExportedFunction Include="_acosh" />
      <EmccExportedFunction Include="_atan" />
      <EmccExportedFunction Include="_atanh" />
      <EmccExportedFunction Include="_cbrt" />
      <EmccExportedFunction Include="_cos" />
      <EmccExportedFunction Include="_cosh" />
      <EmccExportedFunction Include="_exp" />
      <EmccExportedFunction Include="_log" />
      <EmccExportedFunction Include="_log2" />
      <EmccExportedFunction Include="_log10" />
      <EmccExportedFunction Include="_sin" />
      <EmccExportedFunction Include="_sinh" />
      <EmccExportedFunction Include="_tan" />
      <EmccExportedFunction Include="_tanh" />

      <EmccExportedFunction Include="_asinf" />
      <EmccExportedFunction Include="_asinhf" />
      <EmccExportedFunction Include="_acosf" />
      <EmccExportedFunction Include="_acoshf" />
      <EmccExportedFunction Include="_atanf" />
      <EmccExportedFunction Include="_atanhf" />
      <EmccExportedFunction Include="_cbrtf" />
      <EmccExportedFunction Include="_cosf" />
      <EmccExportedFunction Include="_coshf" />
      <EmccExportedFunction Include="_expf" />
      <EmccExportedFunction Include="_logf" />
      <EmccExportedFunction Include="_log2f" />
      <EmccExportedFunction Include="_log10f" />
      <EmccExportedFunction Include="_sinf" />
      <EmccExportedFunction Include="_sinhf" />
      <EmccExportedFunction Include="_tanf" />
      <EmccExportedFunction Include="_tanhf" />
    </ItemGroup>
    <ItemGroup Condition="'$(WasmEnableThreads)' == 'true'">
      <EmccExportedFunction Include="_emscripten_main_runtime_thread_id"  />
    </ItemGroup>
    <ItemGroup Condition="'$(WasmEnableThreads)' == 'true'">
      <EmccExportedFunction Include="_emscripten_main_runtime_thread_id"  />
    </ItemGroup>
    <PropertyGroup>
      <_EmccExportedLibraryFunction>"[@(EmccExportedLibraryFunction -> '%27%(Identity)%27', ',')]"</_EmccExportedLibraryFunction>
      <_EmccExportedRuntimeMethods>"[@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]"</_EmccExportedRuntimeMethods>
      <_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')</_EmccExportedFunctions>
      <!-- reserve at least enough space to complete initializing sgen without growing the heap -->
      <EmccInitialHeapSize>33554432</EmccInitialHeapSize>
      <EmccStackSize>5MB</EmccStackSize>
    </PropertyGroup>
    <ItemGroup>
      <_EmccLinkFlags Include="-s INITIAL_MEMORY=$(EmccInitialHeapSize)" />
      <_EmccLinkFlags Include="-s STACK_SIZE=$(EmccStackSize)" />
      <_EmccCommonFlags Condition="'$(WasmEnableThreads)' == 'true'" Include="-s USE_PTHREADS=1" />
      <_EmccLinkFlags Condition="'$(WasmEnableThreads)' == 'true'" Include="-Wno-pthreads-mem-growth" />
      <_EmccLinkFlags Condition="'$(WasmEnableThreads)' == 'true'" Include="-s PTHREAD_POOL_SIZE=0" />
      <_EmccLinkFlags Condition="'$(WasmEnableThreads)' == 'true'" Include="-s PTHREAD_POOL_SIZE_STRICT=0" />
      <_EmccLinkFlags Include="-s ALLOW_MEMORY_GROWTH=1" />
      <!-- for jiterpreter -->
      <_EmccLinkFlags Include="-s ALLOW_TABLE_GROWTH=1" />
      <_EmccLinkFlags Include="-s NO_EXIT_RUNTIME=0" />
      <_EmccLinkFlags Include="-s FORCE_FILESYSTEM=1" />
      <_EmccLinkFlags Condition="'$(_EmccExportedLibraryFunction)' != ''" Include="-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$(_EmccExportedLibraryFunction)" />
      <_EmccLinkFlags Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" />
      <_EmccLinkFlags Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" />
      <_EmccLinkFlags Include="--source-map-base http://example.com" />
      <_EmccLinkFlags Include="-s WASM_BIGINT=1" />
      <_EmccLinkFlags Include="-s EXPORT_NAME=&quot;'createDotnetRuntime'&quot;" />
      <_EmccLinkFlags Include="-s MODULARIZE=1"/>

      <_EmccLinkFlags Include="-s ENVIRONMENT=&quot;web,webview,worker,node,shell&quot;" />
      <!-- remove -Wno-limited-postlink-optimizations once below issue is fixed
           active issue: https://github.com/emscripten-core/emscripten/pull/16727 -->
      <_EmccLinkFlags Include="-Wno-limited-postlink-optimizations"/>
    </ItemGroup>

    <ItemGroup Condition="'$(WasmEnableThreads)' == 'true'">
      <WasmOptConfigurationFlags Include="--enable-threads;--enable-bulk-memory;--enable-sign-ext" />

      <!-- workaround for https://github.com/emscripten-core/emscripten/issues/18034 -->
      <_EmccLinkFlags Include="-s TEXTDECODER=0"/>
    </ItemGroup>

    <ItemGroup Condition="'$(OS)' != 'Windows_NT'">
      <_EmccLinkFlags Include="--profiling-funcs" />
      <_EmccFlags Include="@(_EmccCommonFlags)" />
    </ItemGroup>

    <ItemGroup Condition="'$(OS)' == 'Windows_NT'">
      <_EmccFlags Include="@(_EmccCommonFlags)" />
    </ItemGroup>

    <PropertyGroup>
      <_EmccPropsJson>
<![CDATA[
{
  "items": {
    "EmccProperties": [
      { "identity": "RuntimeEmccVersion",     "value": "$(_EmccVersion)" },
      { "identity": "RuntimeEmccVersionRaw",  "value": "$(_EmccVersionRaw)" },
      { "identity": "RuntimeEmccVersionHash", "value": "$(_EmccVersionHash)" }
    ],
    "WasmOptConfigurationFlags": [@(WasmOptConfigurationFlags -> '%22%(Identity)%22', ',')],
    "EmccDefaultExportedFunctions": [@(EmccExportedFunction -> '%22%(Identity)%22', ',')],
    "EmccDefaultExportedRuntimeMethods": [@(EmccExportedRuntimeMethod -> '%22%(Identity)%22', ',')]
  }
}
]]>
      </_EmccPropsJson>
    </PropertyGroup>

    <WriteLinesToFile File="$(NativeBinDir)src\wasm-props.json"
                      Lines="$(_EmccPropsJson)"
                      Overwrite="true"
                      WriteOnlyWhenDifferent="true" />

    <WriteLinesToFile File="$(_EmccDefaultsRspPath)"
                      Lines="@(_EmccFlags)"
                      WriteOnlyWhenDifferent="true"
                      Overwrite="true" />
    <WriteLinesToFile File="$(_EmccCompileRspPath)"
                      Lines="@(_EmccCompileFlags)"
                      WriteOnlyWhenDifferent="true"
                      Overwrite="true" />
    <WriteLinesToFile File="$(_EmccLinkRspPath)"
                      Lines="@(_EmccLinkFlags)"
                      WriteOnlyWhenDifferent="true"
                      Overwrite="true" />
  </Target>

  <!-- This is a documented target that is invoked by developers in their innerloop work. -->
  <Target Name="BuildWasmRuntimes"
          AfterTargets="Build"
          DependsOnTargets="GenerateEmccPropsAndRspFiles;GenerateManagedToNative;GenerateTimezonesArchive;InstallNpmPackages;BuildWithRollup">

    <ItemGroup>
      <ICULibNativeFiles Include="$(ICULibDir)/libicuuc.a;
                                  $(ICULibDir)/libicui18n.a;
                                  $(ICULibDir)/libicudata.a;
                                  $(BrowserProjectRoot)runtime/hybrid-globalization/segmentation-rules.json" />
      <ICULibFiles Include="$(ICULibDir)/*.dat" />
    </ItemGroup>
    <PropertyGroup>
      <PInvokeTableFile>$(ArtifactsObjDir)wasm/pinvoke-table.h</PInvokeTableFile>
      <InterpToNativeTableFile>$(ArtifactsObjDir)wasm/wasm_m2n_invoke.g.h</InterpToNativeTableFile>

      <CMakeConfigurationEmccFlags Condition="'$(Configuration)' == 'Debug'">-g -Os -s -DDEBUG=1 -DENABLE_AOT_PROFILER=1 -DENABLE_BROWSER_PROFILER=1</CMakeConfigurationEmccFlags>
      <CMakeConfigurationEmccFlags Condition="'$(Configuration)' == 'Release'">-Oz -DENABLE_BROWSER_PROFILER=1</CMakeConfigurationEmccFlags>

      <CMakeConfigurationLinkFlags Condition="'$(Configuration)' == 'Debug'"  >$(CMakeConfigurationEmccFlags) -s ASSERTIONS=1 </CMakeConfigurationLinkFlags>
      <CMakeConfigurationLinkFlags Condition="'$(Configuration)' == 'Release'">-O2</CMakeConfigurationLinkFlags>

      <!-- -lexports.js has the magical property of disabling minification of export names -->
      <CMakeConfigurationLinkFlags>$(CMakeConfigurationLinkFlags) -s EXPORT_ES6=1 -lexports.js</CMakeConfigurationLinkFlags>
      <CMakeConfigurationLinkFlags Condition="'$(WasmEnableSIMD)' == 'true'">$(CMakeConfigurationLinkFlags) -msimd128</CMakeConfigurationLinkFlags>
      <CMakeConfigurationLinkFlags Condition="'$(WasmEnableThreads)' == 'true'">$(CMakeConfigurationLinkFlags) -Wno-pthreads-mem-growth</CMakeConfigurationLinkFlags>
      <CMakeConfigurationLinkFlags                                            >$(CMakeConfigurationLinkFlags) --emit-symbol-map</CMakeConfigurationLinkFlags>

      <CMakeConfigurationEmsdkPath Condition="'$(Configuration)' == 'Release'"> -DEMSDK_PATH=&quot;$(EMSDK_PATH.TrimEnd('\/').Replace('\','/'))&quot;</CMakeConfigurationEmsdkPath>

      <CMakeBuildRuntimeConfigureCmd>emcmake cmake $(MSBuildThisFileDirectory)runtime</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCMAKE_BUILD_TYPE=$(Configuration)</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_EMCC_FLAGS=&quot;$(CMakeConfigurationEmccFlags)&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_LINK_FLAGS=&quot;$(CMakeConfigurationLinkFlags)&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_WASM_OPT_FLAGS=&quot;@(WasmOptConfigurationFlags, ';')&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DMONO_INCLUDES=&quot;$(MonoArtifactsPath)include/mono-2.0&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DMONO_OBJ_INCLUDES=&quot;$(MonoObjDir.TrimEnd('\/').Replace('\','/'))&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DICU_LIB_DIR=&quot;$(ICULibDir.TrimEnd('\/').Replace('\','/'))&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DMONO_ARTIFACTS_DIR=&quot;$(MonoArtifactsPath.TrimEnd('\/').Replace('\','/'))&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) -DNATIVE_BIN_DIR=&quot;$(NativeBinDir.TrimEnd('\/').Replace('\','/'))&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(WasmEnableSIMD)' == 'true'">$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_COMPILE_OPTIONS=&quot;-msimd128&quot; -DCONFIGURATION_INTERPSIMDTABLES_LIB=&quot;simd&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(WasmEnableSIMD)' != 'true'">$(CMakeBuildRuntimeConfigureCmd) -DCONFIGURATION_INTERPSIMDTABLES_LIB=&quot;nosimd&quot;</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(WasmEnableThreads)' == 'true'">$(CMakeBuildRuntimeConfigureCmd) -DDISABLE_THREADS=0</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(WasmEnableJsInteropByValue)' == 'true'">$(CMakeBuildRuntimeConfigureCmd) -DENABLE_JS_INTEROP_BY_VALUE=1</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd>$(CMakeBuildRuntimeConfigureCmd) $(CMakeConfigurationEmsdkPath)</CMakeBuildRuntimeConfigureCmd>

      <CMakeBuildRuntimeConfigureCmd Condition="'$(OS)' == 'Windows_NT'">call &quot;$(RepositoryEngineeringDir)native\init-vs-env.cmd&quot; &amp;&amp; call &quot;$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env.bat'))&quot; &amp;&amp; $(CMakeBuildRuntimeConfigureCmd)</CMakeBuildRuntimeConfigureCmd>
      <CMakeBuildRuntimeConfigureCmd Condition="'$(OS)' != 'Windows_NT'">bash -c 'source $(EMSDK_PATH)/emsdk_env.sh 2>&amp;1 &amp;&amp; $(CMakeBuildRuntimeConfigureCmd)'</CMakeBuildRuntimeConfigureCmd>

      <CMakeOptions Condition="'$(MonoVerboseBuild)' != ''">-v</CMakeOptions>
      <CMakeBuildRuntimeCmd>cmake --build . --config $(Configuration) $(CmakeOptions)</CMakeBuildRuntimeCmd>
      <CMakeBuildRuntimeCmd Condition="'$(OS)' == 'Windows_NT'">call &quot;$(RepositoryEngineeringDir)native\init-vs-env.cmd&quot; &amp;&amp; call &quot;$([MSBuild]::NormalizePath('$(EMSDK_PATH)', 'emsdk_env.bat'))&quot; &amp;&amp; $(CMakeBuildRuntimeCmd)</CMakeBuildRuntimeCmd>
      <CMakeBuildRuntimeCmd Condition="'$(OS)' != 'Windows_NT'">bash -c 'source $(EMSDK_PATH)/emsdk_env.sh 2>&amp;1 &amp;&amp;  $(CMakeBuildRuntimeCmd)'</CMakeBuildRuntimeCmd>
    </PropertyGroup>
    <ItemGroup>
      <_CmakeEnvironmentVariable Include="ENABLE_JS_INTEROP_BY_VALUE=1" Condition="'$(WasmEnableJsInteropByValue)' != 'false'"/>
      <_CmakeEnvironmentVariable Include="ENABLE_JS_INTEROP_BY_VALUE=0" Condition="'$(WasmEnableJsInteropByValue)' == 'false'"/>
      <_CmakeEnvironmentVariable Include="WASM_ENABLE_SIMD=1" Condition="'$(WasmEnableSIMD)' != 'false'" />
      <_CmakeEnvironmentVariable Include="WASM_ENABLE_SIMD=0" Condition="'$(WasmEnableSIMD)' == 'false'" />
      <_CmakeEnvironmentVariable Include="WASM_ENABLE_EH=1" Condition="'$(WasmEnableExceptionHandling)' != 'false'" />
      <_CmakeEnvironmentVariable Include="WASM_ENABLE_EH=0" Condition="'$(WasmEnableExceptionHandling)' == 'false'" />
      <_CmakeEnvironmentVariable Include="RUN_AOT_COMPILATION=1" Condition="'$(RunAOTCompilation)' == 'true'" />
      <_CmakeEnvironmentVariable Include="RUN_AOT_COMPILATION=0" Condition="'$(RunAOTCompilation)' != 'true'" />
    </ItemGroup>

    <Copy SourceFiles="$(PInvokeTableFile)"
          DestinationFolder="$(MonoObjDir)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="$(InterpToNativeTableFile)"
          DestinationFolder="$(MonoObjDir)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="runtime/runtime.h;
                       runtime/runtime.c;
                       runtime/driver.c;
                       runtime/pinvoke.c;
                       runtime/corebindings.c;"
          DestinationFolder="$(NativeBinDir)src"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="runtime/es6/dotnet.es6.pre.js;
                       runtime/es6/dotnet.es6.lib.js;
                       runtime/es6/dotnet.es6.extpost.js;"
          DestinationFolder="$(NativeBinDir)src/es6"
          SkipUnchangedFiles="true" />

    <ReadLinesFromFile File="$(WasmObjDir)/exports-linker.js">
      <Output TaskParameter="Lines" ItemName="_WasmImportedMethodNames" />
    </ReadLinesFromFile>
    <!-- append at the end of dotnet.es6.lib.js -->
    <WriteLinesToFile File="$(NativeBinDir)src/es6/dotnet.es6.lib.js"
                      Lines="@(_WasmImportedMethodNames)"
                      Overwrite="false" />

    <Copy SourceFiles="runtime\runtime.h;runtime\pinvoke.h;runtime\gc-common.h"
          DestinationFolder="$(NativeBinDir)include\wasm"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(ICULibFiles);
                       @(ICULibNativeFiles);
                       @(_WasmArchivedTimezones);"
          DestinationFolder="$(NativeBinDir)"
          SkipUnchangedFiles="true" />

    <Exec Command="$(CMakeBuildRuntimeConfigureCmd)" WorkingDirectory="$(NativeBinDir)"
          EnvironmentVariables="@(_CmakeEnvironmentVariable)" />
    <Exec Command="$(CMakeBuildRuntimeCmd)"  WorkingDirectory="$(NativeBinDir)"
          EnvironmentVariables="@(_CmakeEnvironmentVariable)" />

    <ItemGroup>
      <IcuDataFiles Include="$(NativeBinDir)*.dat" />
      <WasmSrcFiles Include="$(NativeBinDir)src\*.c;
                             $(NativeBinDir)src\*.js;
                             $(_EmccDefaultsRspPath);
                             $(_EmccCompileRspPath);
                             $(_EmccLinkRspPath);
                             $(NativeBinDir)src\wasm-props.json" />
      <WasmSrcFilesEs6 Include="$(NativeBinDir)src\es6\*.js;" />
      <WasmHeaderFiles Include="$(NativeBinDir)include\wasm\*.h" />
    </ItemGroup>

    <Copy SourceFiles="$(NativeBinDir)dotnet.js;
                       $(NativeBinDir)dotnet.js.map;
                       $(NativeBinDir)dotnet.runtime.js;
                       $(NativeBinDir)dotnet.runtime.js.map;
                       $(NativeBinDir)dotnet.native.js;
                       $(NativeBinDir)dotnet.d.ts;
                       $(NativeBinDir)package.json;
                       $(NativeBinDir)dotnet.native.wasm"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="$(NativeBinDir)dotnet.native.worker.js"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)"
	  Condition="Exists('$(NativeBinDir)dotnet.native.worker.js')"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="$(NativeBinDir)dotnet.native.js.symbols"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(IcuDataFiles);@(ICULibNativeFiles);@(_WasmArchivedTimezones)"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(WasmSrcFiles)"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)src"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(WasmSrcFilesEs6)"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)src\es6"
          SkipUnchangedFiles="true" />

    <Copy SourceFiles="@(WasmHeaderFiles)"
          DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)include\wasm"
          SkipUnchangedFiles="true" />
  </Target>

  <Target Name="InstallNpmPackages"
          Inputs="$(BrowserProjectRoot)runtime/package.json"
          Outputs="$(BrowserProjectRoot)runtime/node_modules/.npm-stamp"
          >
    <!-- install typescript and rollup -->
    <RunWithEmSdkEnv Condition="'$(ContinuousIntegrationBuild)' == 'true'" Command="npm ci" EmSdkPath="$(EMSDK_PATH)" IgnoreStandardErrorWarningFormat="true" WorkingDirectory="$(BrowserProjectRoot)runtime/"/>
    <!-- npm install is faster on dev machine as it doesn't wipe node_modules folder -->
    <RunWithEmSdkEnv Condition="'$(ContinuousIntegrationBuild)' != 'true'" Command="npm install" EmSdkPath="$(EMSDK_PATH)" IgnoreStandardErrorWarningFormat="true" WorkingDirectory="$(BrowserProjectRoot)runtime/"/>

    <!-- Delete malformed package.json used for tests, it confuses Component Governance tooling -->
    <Delete Files="$(BrowserProjectRoot)runtime/node_modules/resolve/test/resolver/malformed_package_json/package.json" ContinueOnError="true" />

    <Touch Files="$(BrowserProjectRoot)runtime/node_modules/.npm-stamp" AlwaysCreate="true" />
  </Target>

  <ItemGroup>
    <_RollupInputs Include="$(BrowserProjectRoot)runtime/**/*.ts"
		   Exclude="$(BrowserProjectRoot)runtime/dotnet.d.ts;$(BrowserProjectRoot)runtime/diagnostics-mock.d.ts;$(BrowserProjectRoot)runtime/node_modules/**/*.ts" />
    <_RollupInputs Include="$(BrowserProjectRoot)runtime/**/tsconfig.*"
		   Exclude="$(BrowserProjectRoot)runtime/node_modules/**/tsconfig.*" />
    <_RollupInputs Include="$(BrowserProjectRoot)runtime/workers/**/*.js"/>
    <_RollupInputs Include="$(BrowserProjectRoot)runtimetypes/*.d.ts"/>
    <_RollupInputs Include="$(BrowserProjectRoot)runtime/*.json"/>
    <_RollupInputs Include="$(BrowserProjectRoot)runtime/*.js"/>
  </ItemGroup>

  <Target Name="SetMonoRollupEnvironment" DependsOnTargets="GetProductVersions">
    <ItemGroup>
      <_MonoRollupEnvironmentVariable Include="Configuration:$(Configuration)" />
      <_MonoRollupEnvironmentVariable Include="NativeBinDir:$(NativeBinDir)" />
      <_MonoRollupEnvironmentVariable Include="WasmObjDir:$(WasmObjDir)" />
      <_MonoRollupEnvironmentVariable Include="ProductVersion:$(ProductVersion)" />
      <_MonoRollupEnvironmentVariable Include="WasmEnableThreads:$(WasmEnableThreads)" />
      <_MonoRollupEnvironmentVariable Include="WASM_ENABLE_SIMD:1" Condition="'$(WasmEnableSIMD)' != 'false'" />
      <_MonoRollupEnvironmentVariable Include="WASM_ENABLE_SIMD:0" Condition="'$(WasmEnableSIMD)' == 'false'" />
      <_MonoRollupEnvironmentVariable Include="WASM_ENABLE_EH:1" Condition="'$(WasmEnableExceptionHandling)' != 'false'" />
      <_MonoRollupEnvironmentVariable Include="WASM_ENABLE_EH:0" Condition="'$(WasmEnableExceptionHandling)' == 'false'" />
      <_MonoRollupEnvironmentVariable Include="ENABLE_JS_INTEROP_BY_VALUE:1" Condition="'$(WasmEnableJsInteropByValue)' == 'true'" />
      <_MonoRollupEnvironmentVariable Include="ENABLE_JS_INTEROP_BY_VALUE:0" Condition="'$(WasmEnableJsInteropByValue)' != 'true'" />
      <_MonoRollupEnvironmentVariable Include="MonoDiagnosticsMock:$(MonoDiagnosticsMock)" />
      <_MonoRollupEnvironmentVariable Include="ContinuousIntegrationBuild:$(ContinuousIntegrationBuild)" />
    </ItemGroup>

    <PropertyGroup>
      <MonoRollupEnvironment>@(_MonoRollupEnvironmentVariable, ',')</MonoRollupEnvironment>
    </PropertyGroup>

    <PropertyGroup>
      <_RollupEnvIntermediateFile>$(WasmObjDir)\.rollup.env</_RollupEnvIntermediateFile>
    </PropertyGroup>
  </Target>

  <Target Name="WriteRollupEnvToFile" DependsOnTargets="SetMonoRollupEnvironment">
    <!-- the purpose of this file is to be an input to the BuildWithRollup target.  That way if any
         of the environment values change, we will do a new rollup build.  For example if the
         `WasmEnableThreads` property is changed between builds by a developer. -->
    <WriteLinesToFile File="$(_RollupEnvIntermediateFile)"
		      Lines="$(MonoRollupEnvironment)"
		      WriteOnlyWhenDifferent="true"
		      Overwrite="true" />
  </Target>

  <Target Name="GenerateMintopsTS"
          Inputs="$(MonoProjectRoot)wasm\runtime\genmintops.py;$(MonoProjectRoot)mono\mini\interp\mintops.def;$(MonoProjectRoot)mono\mini\interp\interp-simd-intrins.def"
          Outputs="$(NativeGeneratedFilesDir)mintops.ts">
      <Exec Command="$(PythonCmd) $(BrowserProjectRoot)runtime/genmintops.py $(MonoProjectRoot)mono/mini/interp/mintops.def $(MonoProjectRoot)mono/mini/interp/interp-simd-intrins.def $(NativeGeneratedFilesDir)mintops.ts" />
  </Target>

  <Target Name="BuildWithRollup"
          Inputs="@(_RollupInputs);$(_RollupEnvIntermediateFile);$(NativeGeneratedFilesDir)mintops.ts"
          Outputs="$(NativeBinDir).rollup-stamp"
	  DependsOnTargets="WriteRollupEnvToFile;GenerateMintopsTS"
          >
    <!-- code style check -->
    <RunWithEmSdkEnv Command="npm run lint" StandardOutputImportance="High" EmSdkPath="$(EMSDK_PATH)" WorkingDirectory="$(BrowserProjectRoot)runtime/"/>

    <!-- compile typescript -->
    <RunWithEmSdkEnv Command="npm run rollup -- --environment $(MonoRollupEnvironment)" EmSdkPath="$(EMSDK_PATH)" IgnoreStandardErrorWarningFormat="true" WorkingDirectory="$(BrowserProjectRoot)runtime/"/>

    <Copy SourceFiles="runtime/package.json;"
          DestinationFolder="$(NativeBinDir)"
          SkipUnchangedFiles="true" />

    <!-- set version -->
    <RunWithEmSdkEnv Command="npm version $(PackageVersion)" EmSdkPath="$(EMSDK_PATH)" WorkingDirectory="$(NativeBinDir)"/>

    <Touch Files="$(NativeBinDir).rollup-stamp" AlwaysCreate="true" />
  </Target>
</Project>
